<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="button" id="btn" value="test" />
    <script>
      /*
                    普通对象里面的this 指向window
              普通对象里面的普通函数this指向当前对象，如只是key 指向window
              普通函数执行，看谁是调用者例如obj.demo demo前面的点是谁this就是谁
              new 构造函数里面的this指向当前实例
              箭头函数本身没有this，this都指向上下文，定义该函数所有在作用域指向的对象
              */
      ~(function () {
        var name = '张三';
        let obj = {
          name: '李四',
          name2: this.name, //this指向winodw
          fun: function () {
            console.log(this.name);
          },
        };
        console.log(obj.name2); //张三
        obj.fun(); //执行 this.name  李四
      })();

      ~(function () {
        //给元素绑定事件，事件触发，一般情况下都是元素本身
        btn.onclick = function () {
          console.log(this); //本身
        };
        // dom2
        btn.addEventListener(
          'click',
          function fun() {
            console.log(this); //本身
          },
          false
        );

        function fn() {
          console.log(this); //本身
        }
        btn.onclick = fn;

        function fn() {
          console.log(this); //window
        }
        btn.onclick = fn();

        function fn() {
          console.log(this); //window
        }
        btn.onclick = fn.bind(window);
      })();

      ~(function () {
        //普通函数执行，里面的this是谁，看调用方法前面是否有’点‘，有的话’点前面是谁就是谁‘ 没有就是window 在严格模式下是undefined
        btn.onclick = function () {
          console.log(this); //本身
        };
        // dom2
        btn.addEventListener(
          'click',
          function fun() {
            console.log(this); //本身
          },
          false
        );

        function fn() {
          console.log(this); //本身
        }
        btn.onclick = fn;

        function fn() {
          console.log(this); //window
        }
        btn.onclick = fn();

        function fn() {
          console.log(this); //window
        }
        btn.onclick = fn.bind(window);
      })();

      ~(function () {
        // 构造函数执行 函数中的this是当前类的实例
        function fn() {
          console.log(this); //当前实例设置的私有属性
        }
        let f = new fn();
      })();

      ~(function () {
        // 箭头函数本身没有this，所用到的this都执行上下问的this(箭头函数不止没有this 也没有prototype,没有构造器，所以不能被new) ,如果需要实参集合 ...args 箭头函数体内的this对象，就是定义该函数所有在作用域指向的对象

        //   1.当函数作为对象的方法被调用时，它的this值就是该对象

        //  2.当对象方法中又嵌套了函数，this指向会出现困扰
        // let obj = {
        //   fn: (...args) => {
        //     console.log(this); //winodw
        //   },
        // };
        // obj.fn();

        let obj = {
          aa: function () {
            var bb = function () {
              console.log(this); //指向window
            };
          },
        };
        let obj2 = {
          aa() {
            let bb = () => {
              console.log(this); //指向函数aa
            };
            bb();
          },
        };
        obj.aa();
      })();

      ~(function () {
        //关于args入参实际取值问题：
        let obj = {};
        obj.fn = function () {
          let arrow = (...args) => {
            console.log('入参列表 : ', arguments); //Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
            console.log('剩余参数 : ', args); // [4, 5, 6]
          };
          arrow(4, 5, 6);
        };
        obj.fn(1, 2, 3);
      })();

      ~(function () {
        // 更改this
        // let obj = {
        //   name: 'a',
        //   fn: function () {
        //     console.log(this); //obj
        //     return function () {
        //       console.log(this); //window
        //     };
        //   },
        // };
        // let aa = obj.fn();
        // aa();
        // //将return的函数this 指向改变
        // // 第一种方式创建变量
        // let obj = {
        //   name: 'a',
        //   fn: function () {
        //     console.log(this); //obj
        //     let _this = this;
        //     return function () {
        //       console.log(_this); //obj
        //     };
        //   },
        // };
        // let aa = obj.fn();
        // aa();
        //第二种箭头函数
        let obj = {
          name: 'a',
          fn: function () {
            console.log(this); //obj
            return () => {
              console.log(this); //obj
            };
          },
        };
      })();
    </script>
  </body>
</html>
